/**
 * Created by 35894 on 2017/8/4.
 */


angular
    .module("makerspace.component", [])
    .factory("FileItem", function () {

        /**
         * FileUploader中的文件项目
         * @param name 文件名
         * @param finished 是否已经上传,该参数会改变文件的初始状态
         */
        function FileItem(name,finished) {
            this.name = name || "";
            this.isDone = !!finished; //是否经过上传
            this.isSuccess = !!finished; // 上传是否成功
            this.isFailure = false; // 上传是否失败
            this.progress = !finished ? 0 : 100; // 上传进度

        }

        return FileItem;
    })
    .factory("FileUploader", ['$http', 'FileItem', function ($http, FileItem) {

        /**
         * FileUploader主类
         *
         * @param config
         *          {
                 *           uploadUrl:{string},上传文件接口的url,只支持单个文件上传,默认为'upload-file'
                 *           deleteUrl:{string},删除文件接口的url,只支持删除单个文件,默认为‘delete-file'
                 *           filter:{array},接收的文件类型,需要加.号,默认为[],全部接收.
                 *                          使用方法例如['.zip','.jpg','.jpeg']
                 *           maxSize:{number},上传的最大尺寸(单位B),默认为1024*1024
                 *           maxFileNumber:{number},上传的最大文件数量,默认为5
                 *         }
         * @constructor
         */
        function FileUploader(config) {
            this.config = {
                uploadUrl: config.uploadUrl || 'upload-file',
                deleteUrl: config.deleteUrl || 'delete-file',
                filter: config.filter || [],
                maxSize: config.maxSize || 1024 * 1024,
                maxFileNumber: config.maxFileNumber || 5
            };

            this.files = [];
        }

        // 检查文件类型是否符合要求,不符合要求返回true
        FileUploader.prototype._isTypeIllegal = function (type) {
            if (this.config.filter.length === 0) {
                return false;
            }

            return this.config.filter.lastIndexOf(type) === -1;
        };

        // 检查文件是否重复,如果重复返回true
        FileUploader.prototype._isFileDuplicate = function (name) {
            for (var i = 0; i < this.files.length; i++) {
                console.log(this.files);
                console.log(name);
                if (this.files[i].name === name) {
                    return true;
                }
            }

            return false;

        };

        /**
         * 检查文件数量是否符合要求,不符合要求返回true
         */
        FileUploader.prototype._isFileNumberOverflow = function (number) {
            return this.files.length + number > this.config.maxFileNumber;
        };

        /**
         * 检查文件尺寸是否符合要求，不符合返回true
         */
        FileUploader.prototype._isSizeOverflow = function (size) {
            return this.config.maxSize < size;
        };


        /**
         * 检查全部要求的项目,有一项不符合则提示,并返回true
         * @param files html5 FileList对象
         */
        FileUploader.prototype.check = function (files) {
            for (var i = 0; i < files.length; i++) {
                var file = files[i];
                if (this._isTypeIllegal(file.name.slice(file.name.lastIndexOf(".")))) {
                    alert("上传的文件类型不符合要求!");
                    return true;
                }

                if (this._isSizeOverflow(file.size)) {
                    alert("上传的文件尺寸超出范围!");
                    return true;
                }

                if (this._isFileNumberOverflow(files.length)) {
                    alert("上传的文件数超出限制!");
                    return true;
                }

                if (this._isFileDuplicate(file.name)) {
                    alert("要上传相同的文件，请先移除已上传的文件");
                    return true;
                }
            }

            return false;
        };

        /**
         * 添加文件,会自动启动上传
         * @param file html5 File对象
         * @param params 随着文件一起上传的参数,封装在对象里边
         */
        FileUploader.prototype.addFile = function (file,params) {
            var fileItem = new FileItem(file.name);

            this.files.push(fileItem);

            var obj = this;
            var formData = new FormData();
            formData.append("file", file);

            // 添加上传的参数
            if(params) {
                for(var param in params) {
                    formData.append(param,params[param]);
                }
            }

            $http({
                url: obj.config.uploadUrl,
                method: 'POST',
                data: formData,
                headers: {
                    'Content-Type': undefined
                },
                // 进度处理器
                uploadEventHandlers: {
                    progress: function (e) {
                        if (e.lengthComputable) {
                            fileItem.progress = (e.loaded / e.total) * 100;
                            console.log("uploading file: ", file.name, ",progress: ", fileItem.progress);
                        }
                    }
                }
            }).then(
                function success(resp) {
                    fileItem.isDone = true;
                    fileItem.isSuccess = true;
                    fileItem.isFailure = false;
                },
                function error(resp) {
                    fileItem.isDone = true;
                    fileItem.isSuccess = false;
                    fileItem.isFailure = true;
                }
            );

        };

        /**
         * 移除一个文件.
         * @param fileItem 要移除的FileItem对象
         * @param params 除文件名外发送一起发送到后台的参数
         */
        FileUploader.prototype.remove = function (fileItem,params) {

            if(!confirm("确定要移除该文件?")) {
                return;
            }

            var obj = this;

            // 如果上传完成(无论成功与否),向后台请求文件删除
            if (fileItem.isDone && fileItem.isSuccess) {
                var transferData = {
                    fileName:fileItem.name
                };

                // 添加参数
                if(params) {
                    for(var param in params) {
                        transferData[param] = params[param];
                    }
                }

                $http({
                    url: obj.config.deleteUrl,
                    method: 'POST',
                    data: transferData
                }).then(
                    function success(resp) {
                        obj.files.splice(obj.files.lastIndexOf(fileItem), 1);
                        console.log("file ", fileItem.name, " is deleted from server.");
                    },
                    function error() {
                        console.log("file ", fileItem.name, " not deleted.");
                    });
            } else {
                obj.files.splice(obj.files.lastIndexOf(fileItem), 1);
                console.log("file ", fileItem.name, " is removed.");
            }
        };

        return FileUploader;
    }])

    /**
     * 文件上传组件指令,需要将这个指令绑定到input元素上.
     * 该指令内部实际上调用了FileUploader对象的addFile方法.
     */
    .directive("fileSelect", function () {
        return {
            restrict: "A",
            scope: {
                fileUploader: "=",
                params:"="//随文件一起上传的参数,可省略
            },
            link: function (scope, element, attrs) {


                element.bind("change", function (e) {
                    var newFiles = e.target.files;
                    var isError = false;

                    if (scope.fileUploader.check(newFiles)) {
                        isError = true;
                    }

                    if (!isError) {
                        for (var i = 0; i < newFiles.length; i++) {
                            console.log(newFiles[i]);
                            scope.fileUploader.addFile(newFiles[i],scope.params);
                        }
                    }

                    scope.$apply();
                });

            }

        }
    });
